package datastruct.树.线段树.nodes;
import datastruct.树.线段树.SegmentTree.AbstractNode;

public class IntSumWithModNode extends AbstractNode<Integer> {

    static int mod = (int)(1e9+7);

    public IntSumWithModNode() {
        super();
        value = 0;
    }

    @Override
    protected AbstractNode<Integer> supplier() {
        return new IntSumWithModNode();
    }

    @Override
    protected AbstractNode<Integer> updateNotLeaf() {
        this.value = (this.lson.value+this.rson.value)%mod;
        return this;
    }

    @Override
    protected <T extends AbstractNode> T self() {
        return (T) this;
    }

    public enum Operate implements Visitable<IntSumWithModNode,Integer,Void> {
        ADD{
            @Override
            public Void inRange(IntSumWithModNode node, Integer input) {
                node.value = (node.value+input)%mod;
                return null;
            }

            @Override
            public Void notInRange(IntSumWithModNode node, Integer input) {
                return null;
            }

            @Override
            public Void merge(IntSumWithModNode node, Void leftOutput, Void rightOutput) {
                node.updateNotLeaf();
                return null;
            }
        },
        CHANGE{
            @Override
            public Void inRange(IntSumWithModNode node, Integer input) {
                node.value = input%mod;
                return null;
            }

            @Override
            public Void notInRange(IntSumWithModNode node, Integer input) {
                return null;
            }

            @Override
            public Void merge(IntSumWithModNode node, Void leftOutput, Void rightOutput) {
                node.updateNotLeaf();
                return null;
            }
        }
    }

    public enum Queries implements Visitable<IntSumWithModNode,Void,Integer> {
        SUM{
            @Override
            public Integer inRange(IntSumWithModNode node, Void input) {
                return node.value;
            }

            @Override
            public Integer notInRange(IntSumWithModNode node, Void input) {
                return 0;
            }

            @Override
            public Integer merge(IntSumWithModNode node, Integer leftOutput, Integer rightOutput) {
                return (leftOutput+rightOutput)%mod;
            }
        }
    }
}
